package ldh.im.handle;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
import ldh.im.dto.base.ErrorResp;
import ldh.im.dto.business.TransferFile;
import ldh.im.dto.codec.CodecFactory;
import ldh.im.dto.codec.binery.TransferCode;
import ldh.im.dto.enmus.CodecType;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public abstract class FileReceiveHandler extends ChannelInboundHandlerAdapter {

    private boolean isAuth = false;
    private FileOutputStream fileOutputStream = null;
    private TransferFile transferFileData = null;
    private int size = 0;

    @Override
    public void channelRead(ChannelHandlerContext channelHandlerContext, Object obj) throws Exception {
        ByteBuf byteBuf = (ByteBuf) obj;
        if (!isAuth && byteBuf.readableBytes() < 4) {
            return;
        }
        if (!isAuth) {
            byteBuf.markReaderIndex();
            int length = byteBuf.readInt();
            if (byteBuf.readableBytes() >= length) {
                TransferCode transferCode = CodecFactory.getInstance().getTransfer(TransferFile.class, CodecType.binary);
                TransferFile transferFile = (TransferFile) transferCode.getImCoder().decode(byteBuf);
                boolean checker = checkTransferFile(transferFile);
                if (!checker) {
                    ReferenceCountUtil.release(obj);
                    ErrorResp errorResp = new ErrorResp();
                    errorResp.setErrorCode(100);
                    errorResp.setErrorMsg("连接非法！");
                    ChannelFuture channelFuture = channelHandlerContext.write(errorResp);
                    channelFuture.addListener(ChannelFutureListener.CLOSE);
                }
                isAuth = true;
                transferFileData = transferFile;
                String file = createFileName(transferFile);
                fileOutputStream = new FileOutputStream(new File(file));
                size = byteBuf.readableBytes();
                fileOutputStream.write(byteBuf.array(), 0, size);
                ReferenceCountUtil.release(obj);
                return;
            } else {
                byteBuf.resetReaderIndex();
                return;
            }
        }
        if (fileOutputStream == null) {
            throw new RuntimeException("文件流为null");
        }
        ReferenceCountUtil.release(obj);
        int length = byteBuf.readableBytes();
        size += length;
        fileOutputStream.write(byteBuf.array(), 0, length);
        if (size == transferFileData.getSize()) {
            uploadEnd(transferFileData);
            close();
            init();
        }
    }



    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        if (fileOutputStream != null) {
            fileOutputStream.close();
        }
        ctx.fireExceptionCaught(cause);
    }

    private void init() throws IOException {
        isAuth = false;
        transferFileData = null;
        size = 0;
        close();
    }

    // 检查连接是否合法
    protected abstract boolean checkTransferFile(TransferFile transferFile);

    // 创建文件是否正确
    protected abstract String createFileName(TransferFile transferFile);

    // 上传完成
    protected abstract void uploadEnd(TransferFile transferFileData);

    private void close() throws IOException {
        if (fileOutputStream != null) {
            fileOutputStream.close();
        }
        fileOutputStream = null;
    }
}
